﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using iRemote.Forms;
using iRemote.Class;
using System.IO.Ports;
using System.IO;
using System.Configuration;
using System.Threading;
using System.Text.RegularExpressions;


namespace iRemote
{
    /*
     * 程序主窗体
     */
    public partial class iRemote : Form
    {

        public static int control_port_num = 1;//显现选项卡个数（com1-com9）
        public static SerialPort[] ports = new SerialPort[iRemote.control_port_num];//串口对象数组
        public static Channel[] channels = new Channel[iRemote.control_port_num];//控制面板数组
        //public static TabPage[] tabpages = new TabPage[iRemote.control_port_num];//选项卡按数组
        public static String[] channeltoport = new String[iRemote.control_port_num];//面板对应的具体串口

        public static List<byte>[] buffer = new List<byte>[iRemote.control_port_num];//接收数据缓存数组
        //public Boolean[] buffer_lock = new Boolean[iRemote.control_port_num];//接收数据缓存数组
        private static object[] lock_buffer = new object[iRemote.control_port_num]; //缓冲区写锁
        public Byte[][] back_data_receive = new Byte[iRemote.control_port_num][];//上次接收数据
        public Byte[][] new_data_receive = new Byte[iRemote.control_port_num][];//最新接收数据

        public static int[] GP = new int[iRemote.control_port_num];//GP状态位数组
        public static int[] MPS = new int[iRemote.control_port_num];//MPS状态位数组
        public static int[] FPS = new int[iRemote.control_port_num];//FPS状态位数组
        public static int[] EN = new int[iRemote.control_port_num];//EN状态位数组
        public static int[] RESTP = new int[iRemote.control_port_num];//RESTP状态位数组
        public static int[] REMOTE = new int[iRemote.control_port_num];//REMOTE状态位数组
        public static int[] SPA_DPA = new int[iRemote.control_port_num];//SPA_DPA状态位数组
        public static int[] key_checked = new int[iRemote.control_port_num];//key是否验证成功
        public static string[] key = new string[iRemote.control_port_num];//key数组

        public static int[] is_leave_time = new int[iRemote.control_port_num];//串口断开连接计数器

        public int[] receive_data_count = new int[iRemote.control_port_num]; //打开串口接收数据计数（数组）
        public Boolean[] status_ready_init = new Boolean[iRemote.control_port_num]; //打开串口接收数据计数（数组）
        public bool[] listening = new bool[iRemote.control_port_num];//是否没有执行完invoke相关操作（数组）   
        public bool[] is_closing = new bool[iRemote.control_port_num];//是否正在关闭串口，执行Application.DoEvents，并阻止再次invoke（数组）

        public static List<byte[]>[] must_need_to_send = new List<byte[]>[iRemote.control_port_num];//发送（操作+数据）缓冲
        public static List<byte>[] operation_need_to_send = new List<byte>[iRemote.control_port_num];//发送操作缓冲

        public static DateTime[] gain_send_time = new DateTime[iRemote.control_port_num];
        public static double[] gain_send_value = new double[iRemote.control_port_num];

        public String record_folder_path;//日志文件记录总路径
        public FileStream record_file_stream;//日志记录文件流
        public String record_file_path; //日志文件记录为准

        public static int current_index = 0; //当前选项页
        public static int receive_data_length = 26; //数据接收长度

        /*
         * 构造函数，窗体初始化
         */
        public iRemote()
        {
            InitializeComponent();  //初始化FORM上面的控件，加载资源，分配资源
            for(int i =0; i<iRemote.control_port_num;i++)
            {
                channels[i] = new Channel(i);
                ports[i] = new SerialPort();
                //tabpages[i] = new TabPage();
                buffer[i] = new List<byte>(40960);
                lock_buffer[i] = new object();
                back_data_receive[i] = new byte[iRemote.control_port_num];
                new_data_receive[i] = new byte[iRemote.control_port_num];
                GP[i] = 1;
                MPS[i] = 1;
                FPS[i] = 1;
                EN[i] = 0;
                RESTP[i] = 0;
                REMOTE[i]= 1;
                SPA_DPA[i] = 0;
                key_checked[i] = 0;
                is_leave_time[i] = 0;
                receive_data_count[i] = 0;
                status_ready_init[i] = false;
                listening[i] = false;
                is_closing[i] = false;
                must_need_to_send[i] = new List<byte[]>();
                operation_need_to_send[i] = new List<byte>();

                gain_send_time[i] = new DateTime();
                gain_send_value[i] = -1;
            }
            tabInit();
            portInit();

            recordFileInit();
        }

        /*
         * 选项卡初始化
         */
        public void tabInit() {
            for (int i = 0; i < iRemote.control_port_num; i++)
            {
                /*
                tabpages[i].Parent = tabControl1;
                tabpages[i].Name = "tabPage"+(i+1);
                tabpages[i].Text = " Channel" + (i + 1)+" ";
                */
                channels[i].TopLevel = false;// 这一步最重要, 去除子窗体的顶级窗体设置
                channels[i].FormBorderStyle = FormBorderStyle.None;// 去边框标题栏等
                channels[i].Dock = DockStyle.Fill; // 填充
                //channels[i].Parent = tabpages[i];
                channels[i].Parent = panel1;
                channels[i].Show();
                panel1.Enabled = false;
            }
        }

        /*
         * 串口初始化
         */
        public void portInit()
        {
            /*
            * 初始化串口，加载配置文件中的初始配置
            */
            for (int i = 0; i < iRemote.control_port_num; i++)
            {
                try
                {
                    string temp_port_name = ConfigurationManager.AppSettings["PortName" + (i + 1)];
                    iRemote.ports[i].PortName = temp_port_name;
                    channeltoport[i] = temp_port_name;
                }
                catch
                {
                    string temp_port_name = ConfigurationManager.AppSettings["PortName"];
                    iRemote.ports[i].PortName = temp_port_name;
                    channeltoport[i] = temp_port_name;
                }
                //iRemote.ports[i].PortName = temp_port_name;

                try
                {
                    iRemote.ports[i].BaudRate = Convert.ToInt32(ConfigurationManager.AppSettings["BaudRate" + (i + 1)]);
                }
                catch
                {
                    iRemote.ports[i].BaudRate = Convert.ToInt32(ConfigurationManager.AppSettings["BaudRate"]);
                }
                //iRemote.ports[i].BaudRate = Convert.ToInt32(ConfigurationManager.AppSettings["BaudRate"]);
                try
                {
                    iRemote.ports[i].DataBits = Convert.ToInt32(ConfigurationManager.AppSettings["DataBits" + (i + 1)]);
                }
                catch
                {
                    iRemote.ports[i].DataBits = Convert.ToInt32(ConfigurationManager.AppSettings["DataBits"]);
                }
                //iRemote.ports[i].DataBits = Convert.ToInt32(ConfigurationManager.AppSettings["DataBits"]);
                String stop_bit = "1";
                try
                {
                    stop_bit = ConfigurationManager.AppSettings["StopBits" + (i + 1)];
                }
                catch
                {
                    stop_bit = ConfigurationManager.AppSettings["StopBits"];
                }
                //String stop_bit = ConfigurationManager.AppSettings["StopBits"];
                if (stop_bit.Equals("1"))
                    iRemote.ports[i].StopBits = StopBits.One;
                else if (stop_bit.Equals("2"))
                    iRemote.ports[i].StopBits = StopBits.Two;
                else
                    iRemote.ports[i].StopBits = StopBits.None;
                String parity = "None";
                try
                {
                    parity = ConfigurationManager.AppSettings["Parity" + (i + 1)];
                }
                catch
                {
                    parity = ConfigurationManager.AppSettings["Parity"];
                }
                //String parity = ConfigurationManager.AppSettings["Parity"];
                if (parity.Equals("Even"))
                    iRemote.ports[i].Parity = Parity.Even;
                else if (parity.Equals("Mark"))
                    iRemote.ports[i].Parity = Parity.Mark;
                else if (parity.Equals("Odd"))
                    iRemote.ports[i].Parity = Parity.Odd;
                else if (parity.Equals("Space"))
                    iRemote.ports[i].Parity = Parity.Space;
                else
                    iRemote.ports[i].Parity = Parity.None;
                String key = "";
                try
                {
                    key = ConfigurationManager.AppSettings["Key" + (i + 1)];
                }
                catch
                {
                    key = ConfigurationManager.AppSettings["Key"];
                }
                iRemote.key[i] = key;
                iRemote.ports[i].DataReceived += new SerialDataReceivedEventHandler(DataReceived);
            }
        }

        /*
         * 日志记录文件初始化
         */
        public void recordFileInit() 
        {
            //初始化日志文件位置
            if (ConfigurationManager.AppSettings["RecordFolder"].Equals(""))
            {
                string folderPath = System.Environment.GetEnvironmentVariable("ProgramFiles") + @"\iRemote\Record";
                saveConfig("RecordFolder", folderPath);
            }

            //在记录保存文件夹中创建以日期命名的文件夹
            try
            {
                record_folder_path = ConfigurationManager.AppSettings["RecordFolder"];
                string folder_path = record_folder_path + "\\" + DateTime.Now.ToString("yyyyMM");

                if (!Directory.Exists(folder_path))
                {
                    Directory.CreateDirectory(folder_path);
                }
            }
            catch 
            {
                //无法创建文件夹，重新选择日志保存位置
                FolderBrowserDialog dialog = new FolderBrowserDialog();
                dialog.Description = "Please select the folder to record error and status";
                dialog.SelectedPath = record_folder_path;
                if (dialog.ShowDialog() == DialogResult.OK)
                {
                    string folderPath = dialog.SelectedPath;
                    saveConfig("RecordFolder", folderPath);
                    recordFileInit(); 
                }
            }

        }

        /*
         * About信息显示
         */
        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            About about1 = new About();
            about1.ShowDialog();
        } 

        /*
         * 打开帮助文档
         */
        private void helpToolStripMenuItem1_Click(object sender, EventArgs e)
        {
             
            //获取帮助文档路径
            string strFilePath = System.Windows.Forms.Application.StartupPath + @"\Help Documents\help.html";
            
            //打开帮助文档
            System.Diagnostics.Process.Start(strFilePath); 
        }

        /*
         * 退出系统 File->Exit
         */
        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < iRemote.control_port_num; i++)
            {
                if (iRemote.ports[i].IsOpen)
                {
                    MessageBox.Show(ports[i].PortName+" is open, please close it firstly!");
                    break;
                }
                else
                {
                    this.Close();
                }
            }
        }
        
        /*
         * 退出系统 窗体关闭按钮
         */
        private void iRemote_FormClosing(object sender, FormClosingEventArgs e)
        {
            for (int i = 0; i < iRemote.control_port_num; i++)
            {
                if (iRemote.ports[i].IsOpen)
                {
                    MessageBox.Show(ports[i].PortName+" is open, please close it firstly!");
                    e.Cancel = true;
                    break;
                }
            }
            
        }

        /*
         * 选择日志记录位置文件位置
         */
        private void recordToolStripMenuItem_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog dialog = new FolderBrowserDialog();
            
            dialog.Description = "Please select the folder";
            dialog.SelectedPath = record_folder_path;
            if (dialog.ShowDialog() == DialogResult.OK)
            {
                string folderPath = dialog.SelectedPath;
                saveConfig("RecordFolder", folderPath);
                recordFileInit();
                MessageBox.Show("Selected folder:" + folderPath, "Record folder Tips", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }

        /*
         * 关闭文件时将错误和状态信息写入日志文件
         */
        public void writeRecord(String record_str) {
            if (!File.Exists(record_file_path))
            {
                record_file_stream = new FileStream(record_file_path, FileMode.OpenOrCreate);
            }
            else
            {
                record_file_stream = new FileStream(record_file_path, FileMode.Append);
            }
            byte[] byteFile = Encoding.UTF8.GetBytes(record_str);
            //参数：要写入到文件的数据数组，从数组的第几个开始写，一共写多少个字节
            record_file_stream.Write(byteFile, 0, byteFile.Length);
            record_file_stream.Close();
        
        }

        /*
         * 参数设置
         */
        private void setUpToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Setup setup1 = new Setup(current_index);
            setup1.ShowDialog();
        }
        
        /*
         * 打开串口
         */
        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string key_str = iRemote.key[current_index];
            key_str = key_str.Replace(" ", "");
            key_str = key_str.ToUpper();
            string pattern = @"^[0-9A-Z]+$";
            Regex regex = new Regex(pattern);
            if (!regex.IsMatch(key_str) || key_str.Length != 16) 
            {
                MessageBox.Show("The format of key is not right!");
                return;
            }
            if (!iRemote.ports[current_index].IsOpen)
            {
                buffer[current_index].Clear();
                try
                {
                    iRemote.ports[current_index].Open();
                }
                catch
                {
                    MessageBox.Show("UART dose not exist, or taken up by other applications!");
                    return;
                }

                //串口开启设置record保存路径
                record_file_path = record_folder_path + "\\" + DateTime.Now.ToString("yyyyMM") + "\\" + channeltoport[current_index] + "_" + DateTime.Now.ToString("yyyyMMdd") + ".txt";
                String record_str = DateTime.Now.ToString() + " iRemote is restarted." + System.Environment.NewLine;
                writeRecord(record_str.Replace("\n", "\r\n"));

                //发送C6查询吗
                iRemote.sendDataToPort(0xC6,-1,current_index);
                
                //等待1秒，将收到的数据解析完成
                int sleep_time = Convert.ToInt32(ConfigurationManager.AppSettings["ReceiveTimeout"]);
                System.Threading.Thread.Sleep(sleep_time);
                
                if (this.receive_data_count[current_index] <= 0)
                {
                    close_port();
                    MessageBox.Show("Amplifier is not connected!");
                    string error_connect = DateTime.Now.ToString() + " Amplifier is not connected!\r\n";
                    writeRecord(error_connect);
                    return;
                }

                if (iRemote.key_checked[current_index] == 0)
                {
                    Identify ck = new Identify(key_str,current_index);
                    ck.StartPosition = FormStartPosition.CenterScreen;
                    if (ck.ShowDialog() != DialogResult.Yes)
                    {
                        close_port();
                        //MessageBox.Show("The key is not right!");
                        string error_connect = DateTime.Now.ToString() + " The key is not right!\r\n";
                        writeRecord(error_connect);
                        return;
                    }
                }
                status_ready_init[current_index] = true;

                //验证通过，将运行时间写入日志文件
                string run_time_str = "Total running time: " + channels[current_index].convertSecondToTime(channels[current_index].time_count) + System.Environment.NewLine;
                writeRecord(run_time_str.Replace("\n", "\r\n"));

                openToolStripMenuItem.Enabled = false;
                closeToolStripMenuItem.Enabled = true;
                toolStripButton1.Enabled = false;
                toolStripButton2.Enabled = true;
                toolStripButton3.Enabled = false;
                recordToolStripMenuItem.Enabled = false;
                setUpToolStripMenuItem.Enabled = false;

                channels[current_index].port_is_open = true;
                channels[current_index].timer3.Interval = Convert.ToInt32(ConfigurationManager.AppSettings["SendInterval"]);
                channels[current_index].timer3.Enabled = true;
                //channels[current_index].drawGraph();
                //channels[current_index].timer4.Enabled = true;
                channels[current_index].Enabled = true;
                //channels[current_index].time_count = 0;

                /*
                tabpages[current_index].Text = " Channel" + (current_index + 1) + " -- "+channeltoport[current_index];
                tabpages[current_index].Enabled = true;
                 */
                panel1.Enabled = true;

            }
            else
            {
               MessageBox.Show("Port is already Opened!");
            }
        }
        
        /*
         * 关闭串口
         */
        private void closeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //DialogResult dr = MessageBox.Show("Close the serial port connection?", "Close Confirm", MessageBoxButtons.YesNo, MessageBoxIcon.Question,MessageBoxDefaultButton.Button2);
            //if (dr == DialogResult.Yes)
            CloseConfirm cc = new CloseConfirm();
            cc.StartPosition = FormStartPosition.CenterScreen;
            if (cc.ShowDialog() == DialogResult.Yes)
            {
                if (iRemote.ports[current_index].IsOpen)
                {
                    close_port();
                }
                else
                {
                    MessageBox.Show("Port is already Closed!");
                }
            }
        }

        /*
         * 关闭串口相关操作
         */
        public void close_port()
        {
            is_closing[current_index] = true;

            while (listening[current_index])
            {
                Application.DoEvents();
            }
            iRemote.ports[current_index].Close();
            buffer[current_index].Clear();
            back_data_receive[current_index] = new byte[iRemote.control_port_num];
            new_data_receive[current_index] = new byte[iRemote.control_port_num];
            key_checked[current_index] = 0;
            is_leave_time[current_index] = 0;
            must_need_to_send[current_index].Clear();
            operation_need_to_send[current_index].Clear();
            this.receive_data_count[current_index] = 0;
            this.status_ready_init[current_index] = false;

            openToolStripMenuItem.Enabled = true;
            closeToolStripMenuItem.Enabled = false;
            toolStripButton1.Enabled = true;
            toolStripButton2.Enabled = false;
            toolStripButton3.Enabled = true;
            recordToolStripMenuItem.Enabled = true;
            setUpToolStripMenuItem.Enabled = true;

            channels[current_index].richTextBox3.Text = "";
            channels[current_index].reset_light();

            channels[current_index].port_is_open = false;
            channels[current_index].timer3.Enabled = false;
            //channels[current_index].timer4.Enabled = false;
            //channels[current_index].clearDraw();
            //channels[current_index].time_count = 0;
            /*
            tabpages[current_index].Text = " Channel" + (current_index + 1) + " ";
            tabpages[current_index].Enabled = false;
            */
            panel1.Enabled = false;

            is_closing[current_index] = false;
            
        }

        /*
         * 保存配置
         */
        public static void saveConfig(string key,string value)
        {

            /*
             * 运行时配置文件修改
             */
            Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            if (config.AppSettings.Settings[key] != null)
            {
                //修改配置
                config.AppSettings.Settings[key].Value = value;
            }
            else 
            {
                config.AppSettings.Settings.Add(key, value);
            }
            //保存配置
            config.Save(ConfigurationSaveMode.Modified);
            //更新配置
            ConfigurationManager.RefreshSection("appSettings");

        }

        /*
         * 重置串口配置
         */
        public static void resetPort()
        {
            /*
             * 软件原始配置
             */
            ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
            fileMap.ExeConfigFilename = System.Windows.Forms.Application.StartupPath + @"\\App.config";
            Configuration config_real = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);

            /*
             * 软件当前配置
             */
            Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);

            /*
             * 读取原始配置到现有配置中
             */
            config.AppSettings.Settings["PortName"].Value = config_real.AppSettings.Settings["PortName"].Value;
            config.AppSettings.Settings["BaudRate"].Value = config_real.AppSettings.Settings["BaudRate"].Value;
            config.AppSettings.Settings["DataBits"].Value = config_real.AppSettings.Settings["DataBits"].Value;
            config.AppSettings.Settings["StopBits"].Value = config_real.AppSettings.Settings["StopBits"].Value;
            config.AppSettings.Settings["Parity"].Value = config_real.AppSettings.Settings["Parity"].Value;
            
            /*
             * 保存原始配置到现有配置中
             */
            config.Save(ConfigurationSaveMode.Modified);

            //更新配置
            ConfigurationManager.RefreshSection("appSettings");
        }

        /*
         * 重置数据收发配置
         */
        public static void resetDataSend()
        {
            /*
             * 软件原始配置
             */
            ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
            fileMap.ExeConfigFilename = System.Windows.Forms.Application.StartupPath + @"\\App.config";
            Configuration config_real = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);

            /*
             * 软件当前配置
             */
            Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            
            /*
             * 读取原始配置到现有配置中
             */
            config.AppSettings.Settings["SendInterval"].Value = config_real.AppSettings.Settings["SendInterval"].Value;
            config.AppSettings.Settings["ReceiveTimeout"].Value = config_real.AppSettings.Settings["ReceiveTimeout"].Value;

            /*
             * 保存原始配置到现有配置中
             */
            config.Save(ConfigurationSaveMode.Modified);

            //更新配置
            ConfigurationManager.RefreshSection("appSettings");
        }

        /*
         * 串口接收数据处理
         */
        private void DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            int index = 0;
            SerialPort sp = (SerialPort)sender;
            for (int i = 0; i < iRemote.control_port_num; i++)
            {
                if (sp.PortName.Equals(channeltoport[i]) && iRemote.ports[i].IsOpen)
                {
                    index = i;
                }
            }
            if (is_closing[index])
            {
                return;
            }
            listening[index] = true;//设置标记，说明已经开始处理数据。  

            receiveDataInit(sp, index);

            listening[index] = false;
        }

        /*
         * 串口触发式接收数据
         */
        private void receiveDataInit(SerialPort sp, int index)
        {
            is_leave_time[index] = 0; //断开时间设为0
            Byte[] all_receive_data = new Byte[receive_data_length];
            Thread.Sleep(100);  //等待26字节数据发送完毕
            if (sp.IsOpen)
            {
                int length = sp.BytesToRead;
                byte[] temp_receive_data = new byte[length];
                sp.Read(temp_receive_data, 0, temp_receive_data.Length);
                
                lock (lock_buffer[index])
                {
                    buffer[index].AddRange(temp_receive_data);

                    while (buffer[index].Count >= receive_data_length)
                    {
                        if (buffer[index][0] == 0x19 && buffer[index][1] == 0xFB && buffer[index][2] == 0xCD && buffer[index][receive_data_length - 1] == 0xFE)
                        {
                            buffer[index].CopyTo(0, all_receive_data, 0, receive_data_length);
                            buffer[index].RemoveRange(0, receive_data_length);

                            this.receive_data_count[index]++;

                            key_checked[index] = DataFormat.getNeedByteBit(all_receive_data, 24, 5);
                            
                            if (this.status_ready_init[index])
                            {
                                back_data_receive[index] = new byte[iRemote.receive_data_length];
                                back_data_receive[index][19] = 0xFF;
                                back_data_receive[index][20] = 0xFF;
                                back_data_receive[index][21] = 0xFF;
                                back_data_receive[index][22] = 0xFC;
                                back_data_receive[index][23] = 0x80;
                                back_data_receive[index][24] = 0x80;
                                this.status_ready_init[index] = false;
                            }
                            else
                            {
                                back_data_receive[index] = new_data_receive[index];
                            }
                            new_data_receive[index] = all_receive_data;
                            
                            Thread thread = new Thread(delegate() { dealReceiveData(new_data_receive[index], back_data_receive[index], index); });
                            thread.Start();
                        }
                        else
                        {
                            buffer[index].RemoveAt(0);
                        }
               
                    }
                }
            }
        }

        /*
        * 处理接收到的数据
        */
        public void dealReceiveData(Byte[] new_data,Byte[] back_data,int index)
        {
            if (iRemote.ports[current_index].IsOpen && iRemote.key_checked[index]==1)
            {
                Byte[] all_receive_data = new_data;

                Invoke(new MethodInvoker(delegate()
                {
                    GP[index] = DataFormat.getNeedByteBit(all_receive_data, 23, 7);
                    MPS[index] = DataFormat.getNeedByteBit(all_receive_data, 22, 1);
                    FPS[index] = DataFormat.getNeedByteBit(all_receive_data, 22, 2);
                    EN[index] = DataFormat.getNeedByteBit(all_receive_data, 23, 6);
                    RESTP[index] = DataFormat.getNeedByteBit(all_receive_data, 24, 7);
                    REMOTE[index] = DataFormat.getNeedByteBit(all_receive_data, 24, 8);
                    SPA_DPA[index] = DataFormat.getNeedByteBit(all_receive_data, 24, 6);

                    if (GP[index] == 0)
                    {
                        channels[index].button1.Enabled = false;
                        channels[index].button2.Enabled = true;
                        channels[index].button2.Text = "RESET";
                        channels[index].pictureBox3.Image = Image.FromFile(System.Windows.Forms.Application.StartupPath + @"\Image\on.png");
                    }
                    else
                    {
                        channels[index].button1.Enabled = true;

                        channels[index].button2.Text = "ENABLE";
                        channels[index].button2.Enabled = true;
                        channels[index].pictureBox3.Image = Image.FromFile(System.Windows.Forms.Application.StartupPath + @"\Image\off.png");
                    }
                    if (EN[index] == 1)
                    {
                        channels[index].button3.Text = "GAIN SET";
                        channels[index].button3.Enabled = false;
                        channels[index].pictureBox4.Image = Image.FromFile(System.Windows.Forms.Application.StartupPath + @"\Image\off.png");
                    }
                    else
                    {
                        channels[index].button3.Text = "GAIN SET";
                        channels[index].button3.Enabled = true;
                        channels[index].pictureBox4.Image = Image.FromFile(System.Windows.Forms.Application.StartupPath + @"\Image\on.png");
                    }

                    if (RESTP[index] == 0)
                    {
                        channels[index].button4.Text = "Emergency Stop";
                        channels[index].button4.Enabled = true;
                    }
                    else
                    {
                        channels[index].button4.Text = "Reset Emergency Stop";
                        channels[index].button4.Enabled = true;
                    }

                    if (MPS[index] == 1)
                    {
                        channels[index].button1.Text = "ON";
                        channels[index].pictureBox2.Image = Image.FromFile(System.Windows.Forms.Application.StartupPath + @"\Image\off.png");
                    }
                    else
                    {
                        channels[index].button1.Text = "OFF";
                        channels[index].pictureBox2.Image = Image.FromFile(System.Windows.Forms.Application.StartupPath + @"\Image\on.png");

                    }
                    if (FPS[index] == 1)
                    {
                        channels[index].pictureBox1.Image = Image.FromFile(System.Windows.Forms.Application.StartupPath + @"\Image\off.png");
                    }
                    else
                    {
                        channels[index].pictureBox1.Image = Image.FromFile(System.Windows.Forms.Application.StartupPath + @"\Image\on.png");
                    }

                    if (SPA_DPA[index] == 0)
                    {
                        channels[index].label5.Text = "Main Voltage";
                        channels[index].label11.Text = "Vdc";
                    }
                    else
                    {
                        channels[index].label5.Text = "Power Supply";
                        channels[index].label11.Text = "V";
                    }
                    Byte[] output_voltage = DataFormat.getNeedData(all_receive_data, "Output voltage");
                    Byte[] output_current = DataFormat.getNeedData(all_receive_data, "Output current");
                    Byte[] main_voltage = DataFormat.getNeedData(all_receive_data, "Main Voltage");
                    Byte[] field_voltage = DataFormat.getNeedData(all_receive_data, "Field Voltage");
                    Byte[] field_current = DataFormat.getNeedData(all_receive_data, "Field current");
                    Byte[] hour_count = DataFormat.getNeedData(all_receive_data, "Hour");
                    Byte[] minute_second = DataFormat.getNeedData(all_receive_data, "Minute Seconds");
                    Byte[] gain = DataFormat.getNeedData(all_receive_data, "Gain");
                    double output_voltage_value = DataFormat.data_Calculation(output_voltage);
                    double output_current_value = DataFormat.data_Calculation(output_current);
                    double main_voltagee_value = DataFormat.data_Calculation(main_voltage);
                    double field_voltage_value = DataFormat.data_Calculation(field_voltage);
                    double field_current_value = DataFormat.data_Calculation(field_current);
                    int hours = hour_count[0] * 256 + hour_count[1];
                    int minute = minute_second[0] % 60;
                    int second = minute_second[1] % 60;
                    channels[index].time_count = hours * 3600 + minute * 60 + second;
                    double gain_value = DataFormat.data_Calculation(gain);
                    channels[index].textBox1.Text = output_voltage_value.ToString();
                    channels[index].textBox2.Text = output_current_value.ToString();
                    channels[index].textBox3.Text = field_voltage_value.ToString();
                    channels[index].textBox4.Text = field_current_value.ToString();
                    channels[index].textBox5.Text = main_voltagee_value.ToString();
                    channels[index].textBox6.Text = gain_value.ToString();
                    if (Convert.ToInt32(gain_value*40) == gain_send_value[index])
                    {
                        String record_str = gain_send_time[index] + " Gain Set ：" + (gain_send_value[index] / 40) + "%" + System.Environment.NewLine;
                        writeRecord(record_str.Replace("\n", "\r\n"));
                        gain_send_time[index] = new DateTime();
                        gain_send_value[index] = -1;
                    }
                    String error_info = ErrorAndStatus.getErrorInfo(back_data, new_data);
                    if (!error_info.Equals(""))
                    {
                        channels[index].richTextBox3.AppendText(error_info);
                        channels[index].richTextBox3.HideSelection = false;

                        String record_str = error_info;
                        writeRecord(record_str.Replace("\n", "\r\n"));

                        this.WindowState = FormWindowState.Normal;
                        this.Activate();
                    }

                    String status_info_other = ErrorAndStatus.getStatusInfoOther(back_data, new_data);
                    if (!status_info_other.Equals(""))
                    {
                        channels[index].richTextBox3.AppendText(status_info_other);
                        channels[index].richTextBox3.HideSelection = false;
                    }

                    String status_info = ErrorAndStatus.getStatusInfo(back_data, new_data);
                    if (!status_info.Equals(""))
                    {
                        String record_str = status_info;
                        writeRecord(record_str.Replace("\n", "\r\n"));
                    }
                }));
            }

        }

        /*
        * 发送数据到串口
        */
        public static void sendDataToPort(Byte operation, Double data,int index) 
        {
            if (iRemote.channels[index].timer3.Enabled && iRemote.channels[index].timer3.Interval<=333)
            {
                if (operation == 0xC5)
                {
                    Byte[] send_data_bytes = DataFormat.getSendData(operation, data);
                    must_need_to_send[index].Add(send_data_bytes);
                }
                else
                {
                    if (!operation_need_to_send[index].Contains(operation))
                    {
                        operation_need_to_send[index].Add(operation);
                    }
                }
            }
            else 
            {
                Byte[] send_data_bytes = DataFormat.getSendData(operation, data);
                iRemote.onlySendDataToPort(send_data_bytes, index);
            }
        }

        /*
         * 单纯发送固定格式数据到串口
         */
        public static void onlySendDataToPort(Byte[] send_data_bytes,int index) 
        {
            if (iRemote.ports[index].IsOpen)
            {
                iRemote.ports[index].Write(send_data_bytes, 0, send_data_bytes.Length);
            }
        }

        /*
        * 定时发送数据到串口
        */
        public static void circularSendDataToPort(Byte operation, Double data, int index)
        {
            if (must_need_to_send[index].Count > 0)
            {
                Byte[] send_data_bytes = must_need_to_send[index][0];
                iRemote.onlySendDataToPort(send_data_bytes, index);
                must_need_to_send[index].RemoveAt(0);
                gain_send_time[index] = DateTime.Now;
                byte[] need_data = new byte[2];
                Array.Copy(send_data_bytes, 3, need_data, 0, 2);
                gain_send_value[index] = DataFormat.data_Calculation(need_data);
            }
            else if (operation_need_to_send[index].Count > 0)
            {
                Byte operation_other = operation_need_to_send[index][0];
                Byte[] send_data_bytes = DataFormat.getSendData(operation_other, -1);
                iRemote.onlySendDataToPort(send_data_bytes, index);
                operation_need_to_send[index].RemoveAt(0);
            }
            else
            {
                Byte[] send_data_bytes = DataFormat.getSendData(operation, data);
                iRemote.onlySendDataToPort(send_data_bytes, index);
            }
        }

        /*
         * 切换选项卡是状态切换
         */
        private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
        {
            //current_index = tabControl1.SelectedIndex;
            if (ports[current_index].IsOpen)
            {
                openToolStripMenuItem.Enabled = false;
                closeToolStripMenuItem.Enabled = true;
                toolStripButton1.Enabled = false;
                toolStripButton2.Enabled = true;
                toolStripButton3.Enabled = false;
                recordToolStripMenuItem.Enabled = false;
                setUpToolStripMenuItem.Enabled = false;

            }
            else
            {
                openToolStripMenuItem.Enabled = true;
                closeToolStripMenuItem.Enabled = false;
                toolStripButton1.Enabled = true;
                toolStripButton2.Enabled = false;
                toolStripButton3.Enabled = true;
                recordToolStripMenuItem.Enabled = true;
                setUpToolStripMenuItem.Enabled = true;
            }
        }

        /*
         * 监测串口是否断开连接
         */
        private void timer1_Tick(object sender, EventArgs e)
        {
            for (int i = 0; i < iRemote.control_port_num; i++)
            {
                if (channels[i].Enabled && channels[i].timer3.Enabled )
                {
                    is_leave_time[i]++;
                }
                if (is_leave_time[i] > 5)
                {
                    //this.tabControl1.SelectTab(tabpages[i].Name);
                    this.WindowState = FormWindowState.Normal;
                    this.Activate();

                    current_index = i;
                    is_leave_time[i] = 0;
                    close_port();

                    MessageBox.Show("Serial port " + channeltoport[i] + " is closed unexpectedly!");
                }
            }
        }


    }
}
